package design.pattern.singleton.register;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Constructor;

/**
 * @description:
 * @author: liuzhangcheng
 **/
public class EnumSingletonTest {
    public static void main(String[] args) {
        // 使用序列化来进行实例化，是否破坏单例
        try {
            EnumSingleton instance1 = null;

            EnumSingleton instance2 = EnumSingleton.getInstance();
            // 设置数据
            instance2.setData(new Object());

            FileOutputStream fos = new FileOutputStream("EnumSingleton.obj");
            ObjectOutputStream oos = new ObjectOutputStream(fos);
            oos.writeObject(instance2);
            oos.flush();
            oos.close();

            FileInputStream fis = new FileInputStream("EnumSingleton.obj");
            ObjectInputStream ois = new ObjectInputStream(fis);
            // ObjectInputStream -> readObject0() ->(TC_ENUM 类型) -> readEnum()
            // -> Enum<?> en = Enum.valueOf((Class)cl, name);
            // 发现枚举类型其实通过类名和 Class 对象类找到一个唯一的枚举对象，枚举对象不可能被类加载器加载多次
            instance1 = (EnumSingleton) ois.readObject();
            ois.close();

            System.out.println(instance1.getData());
            System.out.println(instance2.getData());
            System.out.println(instance1 == instance2);

        } catch (Exception e) {
            e.printStackTrace();
        }

        // 使用反射来进行实例化，是否破坏单例
        try {
            Class clazz = EnumSingleton.class;
            Constructor c = clazz.getDeclaredConstructor();
            c.setAccessible(true);
            // 出现异常：java.lang.NoSuchMethodException: design.pattern.singleton.register.EnumSingleton.<init>()
            // 没有无参构造方法
            c.newInstance();
        }catch (Exception e){
            e.printStackTrace();
        }

        // 打开 java.lang.Enum 的源码代码，查看它的构造方法，只有一个 protected的构造方法
        // protected Enum(String name, int ordinal) { this.name = name; this.ordinal = ordinal; }
        try {
            Class clazz = EnumSingleton.class;
            Constructor c = clazz.getDeclaredConstructor(String.class, int.class);
            c.setAccessible(true);
            // 出现异常：java.lang.IllegalArgumentException: Cannot reflectively create enum objects
            // 不能用反射来创建枚举类型。
            c.newInstance("lzc", 123);
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}
